//
// Created on 2024/7/22.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef HDR2SDR_HDR2SDR_H
#define HDR2SDR_HDR2SDR_H

#include <mutex>
#include <memory>
#include <atomic>
#include <thread>
#include <ohaudio/native_audiorenderer.h>
#include <ohaudio/native_audiostreambuilder.h>
#include <bits/alltypes.h>
#include "av_codec_sample_log.h"
#include "av_codec_sample_error.h"
#include "video_decoder.h"
#include "audio_decoder.h"
#include "demuxer.h"
#include "sample_info.h"
#include "plugin_manager.h"


class Hdr2Sdr {
public:
    int32_t Init(SampleInfo &sampleInfo);
    int32_t Start();
    int32_t Stop();
    int32_t Pause();
    int32_t Resume();
    int32_t VideoSeek(int64_t currentTime);
    int32_t Loop(bool loopFlag);
    int32_t SetSurface(const std::string id);
    int32_t SetSurfaceNative(bool isAuto);
    int32_t WaitForDone();
    
    std::atomic<bool> isStarted{false};
    std::atomic<bool> autoSwitchSurface{false};
    int32_t sampleId = -1;

private:
    void VideoDecInputThread();
    void VideoDecOutputThread();
    void AudioDecInputThread();
    void AudioDecOutputThread();
    int32_t CreateAudioDecoder();
    int32_t CreateVideoDecoder();
    void ReleaseThread();
    void StartRelease();
    void Release();

    std::unique_ptr<VideoDecoder> videoDecoder_ = nullptr;
    std::shared_ptr<AudioDecoder> audioDecoder_ = nullptr;
    std::unique_ptr<Demuxer> demuxer_ = nullptr;
    std::mutex mutex_;
    std::atomic<bool> isLoop{false};
    std::atomic<bool> isPause{false};
    bool switchSurfaceFlag = false;
    std::unique_ptr<std::thread> videoDecInputThread_ = nullptr;
    std::unique_ptr<std::thread> videoDecOutputThread_ = nullptr;
    std::unique_ptr<std::thread> audioDecInputThread_ = nullptr;
    std::unique_ptr<std::thread> audioDecOutputThread_ = nullptr;
    std::condition_variable doneCond_;
    std::unique_ptr<std::thread> releaseThread_ = nullptr;
    SampleInfo sampleInfo_;
    static constexpr int64_t MILLISECONDS = 1000;
    static constexpr int64_t MICROSECOND = 1000000;
    CodecUserData *videoDecContext_ = nullptr;
    CodecUserData *audioDecContext_ = nullptr;
    OH_AudioStreamBuilder* builder_ = nullptr;
    OH_AudioRenderer* audioRenderer_ = nullptr;
#ifdef DEBUG_DECODE
    std::ofstream audioOutputFile_; // for debug
#endif

private:
    int32_t id;
    static int32_t maxNumOfInstance;
    static std::vector<Hdr2Sdr *> multiSurfaceList;
    Hdr2Sdr(){};
    Hdr2Sdr(int32_t id);
    ~Hdr2Sdr();

public:
    static void SetMaxNum(int32_t num);
    static Hdr2Sdr *getInstance(int32_t id);
    static void releaseInstance();
};

#endif //HDR2SDR_HDR2SDR_H
